#import "AssetCollectionView.h"
#import "AssetCollectionViewNode.h"
#import "AssetCollection.h"
#import "SlideCarrierView.h"
#import "ViewLayout.h"
#import <Quartz/Quartz.h>

@implementation AssetCollectionView

- (void)startLayoutCycleTimer {
    if (layoutTimer == nil) {
        layoutTimer = [[NSTimer scheduledTimerWithTimeInterval:[self layoutCycleInterval] target:self selector:@selector(cycleLayout:) userInfo:nil repeats:YES] retain];
    }
}

- (void)stopLayoutCycleTimer {
    if (layoutTimer != nil) {
        [layoutTimer invalidate];
        [layoutTimer release];
        layoutTimer = nil;
    }
}

- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        assetCollection = nil;
        nodes = [[NSMutableArray alloc] init];
        subviewsLayoutType = 4;
        layoutCycleInterval = 3.0;
    }
    return self;
}

- (void)dealloc {
    [self setAutoCyclesLayout:NO];
    [self setAssetCollection:nil];
    [self setSortDescriptors:nil];
    [backgroundGradient release];
    [nodes release];
    [super dealloc];
}

- (BOOL)acceptsFirstMouse {
    return YES;
}

- (NSArray *)animatorsForArrangedSubviews {
    return [[[self animator] subviews] sortedArrayUsingDescriptors:sortDescriptors];
}

- (NSTimeInterval)layoutCycleInterval {
    return layoutCycleInterval;
}

- (void)setLayoutCycleInterval:(NSTimeInterval)newLayoutCycleInterval {
    if (layoutCycleInterval != newLayoutCycleInterval) {
        layoutCycleInterval = newLayoutCycleInterval;
        if ([self autoCyclesLayout]) {
            [self stopLayoutCycleTimer];
            [self startLayoutCycleTimer];
        }
    }
}

- (double)layoutDuration {
    id duration = [[NSUserDefaults standardUserDefaults] objectForKey:@"layoutDuration"];
    if (duration == nil) {
        duration = [NSNumber numberWithDouble:2.5];
        [[NSUserDefaults standardUserDefaults] setObject:duration forKey:@"layoutDuration"];
    }
    return [duration doubleValue];
}

- (void)layoutSubviews {
	NSLog(@"Layout");
    ViewLayout *layout = nil;
    switch (subviewsLayoutType) {
        case 0: layout = [CircularViewLayout viewLayout]; break;
        case 1: layout = [LoopViewLayout viewLayout]; break;
        case 2: layout = [ScatterViewLayout viewLayout]; break;
        case 3: layout = [WrappedViewLayout viewLayout]; break;
    }
    if (layout) {
		
        [NSAnimationContext beginGrouping];
        [[NSAnimationContext currentContext] setDuration:[self layoutDuration]];
        [layout layoutSubviews:[self animatorsForArrangedSubviews] ofView:self];
        [NSAnimationContext endGrouping];
    }
}

- (AssetCollection *)assetCollection {
    return assetCollection;
}

- (void)setAssetCollection:(AssetCollection *)newAssetCollection {
    if (assetCollection != newAssetCollection) {
        
		id old = assetCollection;
        [old removeObserver:self forKeyPath:@"assets"];
		assetCollection = [newAssetCollection retain];
        [old release];
		
        [self reloadData];
		[assetCollection addObserver:self forKeyPath:@"assets" options:0 context:NULL];
    }
}

- (void)cycleLayout:(NSTimer *)timer {
    [self setSubviewsLayoutType:([self subviewsLayoutType] + 1) % 4];
}

- (BOOL)autoCyclesLayout {
    return autoCyclesLayout;
}

- (void)setAutoCyclesLayout:(BOOL)flag {
    if (autoCyclesLayout != flag) {
        autoCyclesLayout = flag;
        if (autoCyclesLayout) {
            [self startLayoutCycleTimer];
            [self cycleLayout:layoutTimer];
        } else {
            [self stopLayoutCycleTimer];
        }
    }
}

- (BOOL)slidesHaveShadows {
    return slidesHaveShadows;
}

- (void)setSlidesHaveShadows:(BOOL)flag {
    if (slidesHaveShadows != flag) {
        slidesHaveShadows = flag;
        NSShadow *shadow = [[[NSShadow alloc] init] autorelease];
        if (slidesHaveShadows) {
            [shadow setShadowOffset:NSMakeSize(3, -3)];
            [shadow setShadowBlurRadius:4.0];
            [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.75]];
        } else {
            [shadow setShadowColor:[NSColor clearColor]];
        }
		
        [NSAnimationContext beginGrouping];
        [[NSAnimationContext currentContext] setDuration:0.5];
        for (AssetCollectionViewNode *node in nodes) {
            [[[node rootView] animator] setShadow:shadow];
        }		
        [NSAnimationContext endGrouping];
    }
}

- (int)subviewsLayoutType {
    return subviewsLayoutType;
}

- (void)setSubviewsLayoutType:(int)layoutType {
    subviewsLayoutType = layoutType;
	[self layoutSubviews];
}

- (NSArray *)sortDescriptors {
    return sortDescriptors;
}

- (void)setSortDescriptors:(NSArray *)newSortDescriptors {
    if (sortDescriptors != newSortDescriptors) {
        id old = sortDescriptors;
        sortDescriptors = [newSortDescriptors copy];
        [old release];
		
        if (sortDescriptors) {
            [self layoutSubviews];
        }
    }
}

- (AssetCollectionViewNode *)insertNodeForAssetAtIndex:(NSUInteger)index {
    Asset *asset = [[[self assetCollection] assets] objectAtIndex:index];
    AssetCollectionViewNode *node = [[AssetCollectionViewNode alloc] init];
    [node setAsset:asset];
    [[self animator] addSubview:[node rootView]];
    [nodes addObject:node];
	
    return [node autorelease];
}

- (void)removeNodeForAssetAtIndex:(NSUInteger)index {
    AssetCollectionViewNode *node = [nodes objectAtIndex:index];
    [[node rootView] removeFromSuperview];
    [nodes removeObjectAtIndex:index];
}

- (void)reloadData {

    NSArray *assets = [[self assetCollection] assets];
    [self setSubviews:[NSArray array]];
    [nodes removeAllObjects];
	
    NSUInteger count = [assets count];
    NSUInteger index;
    for (index = 0; index < count; index++) {
        [self insertNodeForAssetAtIndex:index];
    }
	
    [self layoutSubviews];
}

- (void)handleAssetsInsertedInCatalogAtIndexes:(NSIndexSet *)indexes {
    NSUInteger index = [indexes firstIndex];
    while (index != NSNotFound) {
        [self insertNodeForAssetAtIndex:index];
		[self layoutSubviews];
        [self display];
		
        index = [indexes indexGreaterThanIndex:index];
    }
}

- (void)handleAssetsRemovedFromCatalogAtIndexes:(NSIndexSet *)indexes {
    NSUInteger index = [indexes firstIndex];
    while (index != NSNotFound) {
        [self removeNodeForAssetAtIndex:index];
		[self layoutSubviews];
        [self display];
		
        index = [indexes indexGreaterThanIndex:index];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSKeyValueChange kind = [[change valueForKey:@"kind"] integerValue];
	
    switch (kind) {
			
        case NSKeyValueChangeInsertion:
            [self handleAssetsInsertedInCatalogAtIndexes:[change valueForKey:@"indexes"]];
            break;
			
        case NSKeyValueChangeRemoval:
            [self handleAssetsRemovedFromCatalogAtIndexes:[change valueForKey:@"indexes"]];
            break;
			
        case NSKeyValueChangeSetting:
        default:
            [self reloadData];
            break;
    }
}

- (void)drawRect:(NSRect)rect {
	[self layoutSubviews];
    if (backgroundGradient == nil) {
        backgroundGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.62 alpha:1.0] endingColor:[NSColor colorWithCalibratedWhite:0.68 alpha:1.0]];
    }
    [backgroundGradient drawInRect:[self bounds] angle:90.0];
	
}

- (BOOL)usesQuartzCompositionBackground {
    return usesQuartzCompositionBackground;
}

- (void)setUsesQuartzCompositionBackground:(BOOL)flag {
    if (usesQuartzCompositionBackground != flag) {
        usesQuartzCompositionBackground = flag;
		
        [[self window] disableScreenUpdatesUntilFlush];
        [self setWantsLayer:YES];
        if (usesQuartzCompositionBackground) {
            QCCompositionLayer *qcLayer = [QCCompositionLayer compositionLayerWithFile:[[NSBundle mainBundle] pathForResource:@"Cells" ofType:@"qtz"]];
            [self setLayer:qcLayer];
        } else {
            [self setLayer:nil];         }
        [self setWantsLayer:YES];
    }
}

@end
